/*     */ package com.zimbra.cs.service.admin;
/*     */ 
/*     */ import com.zimbra.common.account.Key.DomainBy;
/*     */ import com.zimbra.common.auth.ZAuthToken;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.AdminConstants;
/*     */ import com.zimbra.common.soap.Element;
/*     */ import com.zimbra.common.soap.SoapHttpTransport;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.AccountServiceException;
/*     */ import com.zimbra.cs.account.Domain;
/*     */ import com.zimbra.cs.account.NamedEntry;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.SearchAccountsOptions;
/*     */ import com.zimbra.cs.account.SearchAccountsOptions.IncludeType;
/*     */ import com.zimbra.cs.account.SearchDirectoryOptions.MakeObjectOpt;
/*     */ import com.zimbra.cs.account.SearchDirectoryOptions.SortOpt;
/*     */ import com.zimbra.cs.account.Server;
/*     */ import com.zimbra.cs.account.accesscontrol.AdminRight;
/*     */ import com.zimbra.cs.account.accesscontrol.Rights.Admin;
/*     */ import com.zimbra.cs.httpclient.URLUtil;
/*     */ import com.zimbra.cs.mailbox.MailboxManager;
/*     */ import com.zimbra.cs.session.AdminSession;
/*     */ import com.zimbra.cs.session.Session.Type;
/*     */ import com.zimbra.cs.util.AccountUtil;
/*     */ import com.zimbra.soap.ZimbraSoapContext;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collections;
/*     */ import java.util.Comparator;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.concurrent.Callable;
/*     */ import java.util.concurrent.ExecutorService;
/*     */ import java.util.concurrent.Executors;
/*     */ import java.util.concurrent.Future;
/*     */ import java.util.concurrent.TimeUnit;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class GetQuotaUsage
/*     */   extends AdminDocumentHandler
/*     */ {
/*     */   public static final String BY_NAME = "name";
/*     */   public static final String BY_ID = "id";
/*     */   public static final String SORT_PERCENT_USED = "percentUsed";
/*     */   public static final String SORT_TOTAL_USED = "totalUsed";
/*     */   public static final String SORT_QUOTA_LIMIT = "quotaLimit";
/*     */   public static final String SORT_ACCOUNT = "account";
/*     */   private static final String QUOTA_USAGE_CACHE_KEY = "GetQuotaUsage";
/*     */   private static final String QUOTA_USAGE_ALL_SERVERS_CACHE_KEY = "GetQuotaUsageAllServers";
/*     */   
/*     */   public Element handle(Element request, Map<String, Object> context)
/*     */     throws ServiceException
/*     */   {
/*  71 */     ZimbraSoapContext zsc = getZimbraSoapContext(context);
/*  72 */     Provisioning prov = Provisioning.getInstance();
/*     */     
/*  74 */     int limit = (int)request.getAttributeLong("limit", 2147483647L);
/*  75 */     if (limit == 0)
/*  76 */       limit = Integer.MAX_VALUE;
/*  77 */     int offset = (int)request.getAttributeLong("offset", 0L);
/*  78 */     String domain = request.getAttribute("domain", null);
/*  79 */     String sortBy = request.getAttribute("sortBy", "totalUsed");
/*  80 */     boolean sortAscending = request.getAttributeBool("sortAscending", false);
/*  81 */     boolean refresh = request.getAttributeBool("refresh", false);
/*     */     
/*  83 */     if ((!sortBy.equals("totalUsed")) && (!sortBy.equals("percentUsed")) && (!sortBy.equals("quotaLimit")) && (!sortBy.equals("account"))) {
/*  84 */       throw ServiceException.INVALID_REQUEST("sortBy must be percentUsed or totalUsed", null);
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  91 */     if (isDomainAdminOnly(zsc))
/*     */     {
/*  93 */       if (domain == null) {
/*  94 */         domain = getAuthTokenAccountDomain(zsc).getName();
/*     */       }
/*     */       
/*  97 */       if (domain == null) {
/*  98 */         throw AccountServiceException.INVALID_REQUEST("no domain", null);
/*     */       }
/*     */     }
/* 101 */     Domain d = null;
/* 102 */     if (domain != null) {
/* 103 */       d = prov.get(Key.DomainBy.name, domain);
/* 104 */       if (d == null) {
/* 105 */         throw AccountServiceException.NO_SUCH_DOMAIN(domain);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 110 */     if (d != null) {
/* 111 */       checkDomainRight(zsc, d, Rights.Admin.R_getDomainQuotaUsage);
/*     */     } else {
/* 113 */       checkRight(zsc, null, AdminRight.PR_SYSTEM_ADMIN_ONLY);
/*     */     }
/* 115 */     boolean allServers = (d != null) && (request.getAttributeBool("allServers", false));
/*     */     
/* 117 */     List<AccountQuota> quotas = null;
/* 118 */     QuotaUsageParams params = new QuotaUsageParams(d, sortBy, sortAscending);
/* 119 */     AdminSession session = (AdminSession)getSession(zsc, Session.Type.ADMIN);
/* 120 */     if (session != null) {
/* 121 */       QuotaUsageParams cachedParams = getCachedQuotaUsage(session, allServers);
/* 122 */       if ((cachedParams != null) && (cachedParams.equals(params)) && (!refresh)) {
/* 123 */         quotas = cachedParams.getResult();
/*     */       }
/*     */     }
/* 126 */     if (quotas == null) {
/* 127 */       if (allServers) {
/* 128 */         quotas = delegateRequestToAllServers(request.clone(), zsc.getRawAuthToken(), sortBy, sortAscending, prov);
/*     */         
/* 130 */         params.setResult(quotas);
/*     */       } else {
/* 132 */         quotas = params.doSearch();
/*     */       }
/* 134 */       if (session != null) {
/* 135 */         setCachedQuotaUsage(session, params, allServers);
/*     */       }
/*     */     }
/*     */     
/* 139 */     Element response = zsc.createElement(AdminConstants.GET_QUOTA_USAGE_RESPONSE);
/* 140 */     int limitMax = offset + limit;
/* 141 */     for (int i = offset; (i < limitMax) && (i < quotas.size()); i++) {
/* 142 */       AccountQuota quota = (AccountQuota)quotas.get(i);
/*     */       
/* 144 */       Element account = response.addElement("account");
/* 145 */       account.addAttribute("name", quota.name);
/* 146 */       account.addAttribute("id", quota.id);
/* 147 */       account.addAttribute("used", quota.quotaUsed);
/* 148 */       account.addAttribute("limit", quota.quotaLimit);
/*     */     }
/* 150 */     response.addAttribute("more", i < quotas.size());
/* 151 */     response.addAttribute("searchTotal", quotas.size());
/* 152 */     return response;
/*     */   }
/*     */   
/*     */ 
/*     */   private List<AccountQuota> delegateRequestToAllServers(final Element request, final ZAuthToken authToken, String sortBy, boolean sortAscending, Provisioning prov)
/*     */     throws ServiceException
/*     */   {
/* 159 */     request.addAttribute("allServers", false);
/*     */     
/* 161 */     request.addAttribute("limit", 0L);
/* 162 */     request.addAttribute("offset", 0L);
/* 163 */     List<Server> servers = prov.getAllMailClientServers();
/*     */     
/* 165 */     ExecutorService executor = Executors.newFixedThreadPool(10);
/* 166 */     List<Future<List<AccountQuota>>> futures = new LinkedList();
/* 167 */     for (final Server server : servers) {
/* 168 */       futures.add(executor.submit(new Callable()
/*     */       {
/*     */         public List<GetQuotaUsage.AccountQuota> call() throws Exception {
/* 171 */           ZimbraLog.misc.debug("Invoking %s on server %s", new Object[] { "GetQuotaUsageRequest", server.getName() });
/* 172 */           String adminUrl = URLUtil.getAdminURL(server, "/service/admin/soap/");
/* 173 */           SoapHttpTransport mTransport = new SoapHttpTransport(adminUrl);
/* 174 */           mTransport.setAuthToken(authToken);
/*     */           Element resp;
/*     */           try {
/* 177 */             resp = mTransport.invoke(request.clone());
/*     */           } catch (Exception e) {
/* 179 */             throw new Exception("Error in invoking GetQuotaUsageRequest on server " + server.getName(), e);
/*     */           }
/*     */           
/* 182 */           List<Element> accountElts = resp.getPathElementList(new String[] { "account" });
/* 183 */           List<GetQuotaUsage.AccountQuota> retList = new ArrayList();
/* 184 */           for (Element accountElt : accountElts) {
/* 185 */             GetQuotaUsage.AccountQuota quota = new GetQuotaUsage.AccountQuota();
/* 186 */             quota.name = accountElt.getAttribute("name");
/* 187 */             quota.id = accountElt.getAttribute("id");
/* 188 */             quota.quotaUsed = accountElt.getAttributeLong("used");
/* 189 */             quota.quotaLimit = accountElt.getAttributeLong("limit");
/* 190 */             retList.add(quota);
/*     */           }
/* 192 */           return retList;
/*     */         }
/*     */       }));
/*     */     }
/* 196 */     shutdownAndAwaitTermination(executor);
/*     */     
/*     */ 
/* 199 */     List<AccountQuota> retList = new ArrayList();
/* 200 */     for (Future<List<AccountQuota>> future : futures) {
/*     */       List<AccountQuota> result;
/*     */       try {
/* 203 */         result = (List)future.get();
/*     */       } catch (Exception e) {
/* 205 */         throw ServiceException.FAILURE("Error in getting task execution result", e);
/*     */       }
/* 207 */       retList.addAll(result);
/*     */     }
/*     */     
/* 210 */     boolean sortByTotal = sortBy.equals("totalUsed");
/* 211 */     boolean sortByQuota = sortBy.equals("quotaLimit");
/* 212 */     boolean sortByAccount = sortBy.equals("account");
/* 213 */     Comparator<AccountQuota> comparator = new QuotaComparator(sortByTotal, sortByQuota, sortByAccount, sortAscending);
/*     */     
/* 215 */     Collections.sort(retList, comparator);
/*     */     
/* 217 */     return retList;
/*     */   }
/*     */   
/*     */   private static void shutdownAndAwaitTermination(ExecutorService executor) throws ServiceException {
/* 221 */     executor.shutdown();
/*     */     
/*     */     try
/*     */     {
/* 225 */       if (!executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {
/* 226 */         throw ServiceException.FAILURE("Time out waiting for GetAggregateQuotaUsageOnServerRequest result", null);
/*     */       }
/*     */     }
/*     */     catch (InterruptedException ie) {
/* 230 */       executor.shutdownNow();
/*     */       
/* 232 */       Thread.currentThread().interrupt();
/*     */     }
/*     */   }
/*     */   
/*     */   static synchronized QuotaUsageParams getCachedQuotaUsage(AdminSession session, boolean allServers) {
/* 237 */     return (QuotaUsageParams)session.getData(allServers ? "GetQuotaUsageAllServers" : "GetQuotaUsage");
/*     */   }
/*     */   
/*     */   static synchronized void setCachedQuotaUsage(AdminSession session, QuotaUsageParams params, boolean allServers) {
/* 241 */     session.setData(allServers ? "GetQuotaUsageAllServers" : "GetQuotaUsage", params);
/*     */   }
/*     */   
/*     */   static synchronized void clearCachedQuotaUsage(AdminSession session) {
/* 245 */     session.clearData("GetQuotaUsage");
/* 246 */     session.clearData("GetQuotaUsageAllServers");
/*     */   }
/*     */   
/*     */   public static class AccountQuota
/*     */   {
/*     */     public String name;
/*     */     public String id;
/*     */     public long quotaLimit;
/*     */     public long sortQuotaLimit;
/*     */     public long quotaUsed;
/*     */     public float percentQuotaUsed;
/*     */   }
/*     */   
/*     */   public class QuotaUsageParams {
/*     */     String domainId;
/*     */     String sortBy;
/*     */     boolean sortAscending;
/*     */     List<GetQuotaUsage.AccountQuota> mResult;
/*     */     
/*     */     QuotaUsageParams(Domain d, String sortBy, boolean sortAscending) {
/* 266 */       this.domainId = (d == null ? "" : d.getId());
/* 267 */       this.sortBy = (sortBy == null ? "" : sortBy);
/* 268 */       this.sortAscending = sortAscending;
/*     */     }
/*     */     
/*     */     public boolean equals(Object o)
/*     */     {
/* 273 */       if (!(o instanceof QuotaUsageParams)) return false;
/* 274 */       if (o == this) { return true;
/*     */       }
/* 276 */       QuotaUsageParams other = (QuotaUsageParams)o;
/* 277 */       return (this.domainId.equals(other.domainId)) && (this.sortBy.equals(other.sortBy)) && (this.sortAscending == other.sortAscending);
/*     */     }
/*     */     
/*     */ 
/*     */     List<GetQuotaUsage.AccountQuota> doSearch()
/*     */       throws ServiceException
/*     */     {
/* 284 */       if (this.mResult != null) { return this.mResult;
/*     */       }
/* 286 */       ArrayList<GetQuotaUsage.AccountQuota> result = new ArrayList();
/*     */       
/* 288 */       Provisioning prov = Provisioning.getInstance();
/*     */       
/* 290 */       SearchAccountsOptions searchOpts = new SearchAccountsOptions();
/* 291 */       searchOpts.setIncludeType(SearchAccountsOptions.IncludeType.ACCOUNTS_ONLY);
/* 292 */       searchOpts.setMakeObjectOpt(SearchDirectoryOptions.MakeObjectOpt.NO_SECONDARY_DEFAULTS);
/* 293 */       searchOpts.setSortOpt(SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*     */       
/* 295 */       Domain d = this.domainId.equals("") ? null : prov.get(Key.DomainBy.id, this.domainId);
/* 296 */       if (d != null) {
/* 297 */         searchOpts.setDomain(d);
/*     */       }
/* 299 */       List<NamedEntry> accounts = prov.searchAccountsOnServer(Provisioning.getInstance().getLocalServer(), searchOpts);
/*     */       
/* 301 */       Map<String, Long> quotaUsed = MailboxManager.getInstance().getMailboxSizes(accounts);
/*     */       
/* 303 */       for (Object obj : accounts) {
/* 304 */         if ((obj instanceof Account)) {
/* 305 */           Account acct = (Account)obj;
/* 306 */           GetQuotaUsage.AccountQuota aq = new GetQuotaUsage.AccountQuota();
/* 307 */           aq.id = acct.getId();
/* 308 */           aq.name = acct.getName();
/* 309 */           aq.quotaLimit = AccountUtil.getEffectiveQuota(acct);
/* 310 */           aq.sortQuotaLimit = (aq.quotaLimit == 0L ? Long.MAX_VALUE : aq.quotaLimit);
/* 311 */           Long used = (Long)quotaUsed.get(acct.getId());
/* 312 */           aq.quotaUsed = (used == null ? 0L : used.longValue());
/* 313 */           aq.percentQuotaUsed = (aq.quotaLimit > 0L ? (float)aq.quotaUsed / (float)aq.quotaLimit : 0.0F);
/* 314 */           result.add(aq);
/*     */         }
/*     */       }
/* 317 */       boolean sortByTotal = this.sortBy.equals("totalUsed");
/* 318 */       boolean sortByQuota = this.sortBy.equals("quotaLimit");
/* 319 */       boolean sortByAccount = this.sortBy.equals("account");
/* 320 */       Comparator<GetQuotaUsage.AccountQuota> comparator = new GetQuotaUsage.QuotaComparator(GetQuotaUsage.this, sortByTotal, sortByQuota, sortByAccount, this.sortAscending);
/*     */       
/* 322 */       Collections.sort(result, comparator);
/* 323 */       this.mResult = result;
/* 324 */       return this.mResult;
/*     */     }
/*     */     
/*     */     List<GetQuotaUsage.AccountQuota> getResult() {
/* 328 */       return this.mResult;
/*     */     }
/*     */     
/*     */     void setResult(List<GetQuotaUsage.AccountQuota> result) {
/* 332 */       this.mResult = result;
/*     */     }
/*     */   }
/*     */   
/*     */   public class QuotaComparator implements Comparator<GetQuotaUsage.AccountQuota> {
/*     */     private final boolean sortByTotal;
/*     */     private final boolean sortByQuota;
/*     */     private final boolean sortByAccount;
/*     */     private final boolean sortAscending;
/*     */     
/*     */     public QuotaComparator(boolean sortByTotal, boolean sortByQuota, boolean sortByAccount, boolean sortAscending) {
/* 343 */       this.sortByTotal = sortByTotal;
/* 344 */       this.sortByQuota = sortByQuota;
/* 345 */       this.sortByAccount = sortByAccount;
/* 346 */       this.sortAscending = sortAscending;
/*     */     }
/*     */     
/*     */     public int compare(GetQuotaUsage.AccountQuota a, GetQuotaUsage.AccountQuota b)
/*     */     {
/* 351 */       int comp = 0;
/* 352 */       if (this.sortByTotal) {
/* 353 */         if (a.quotaUsed > b.quotaUsed) { comp = 1;
/* 354 */         } else if (a.quotaUsed < b.quotaUsed) comp = -1;
/* 355 */       } else if (this.sortByQuota) {
/* 356 */         if (a.sortQuotaLimit > b.sortQuotaLimit) { comp = 1;
/* 357 */         } else if (a.sortQuotaLimit < b.sortQuotaLimit) comp = -1;
/* 358 */       } else if (this.sortByAccount) {
/* 359 */         comp = a.name.compareToIgnoreCase(b.name);
/*     */       }
/* 361 */       else if (a.percentQuotaUsed > b.percentQuotaUsed) { comp = 1;
/* 362 */       } else if (a.percentQuotaUsed < b.percentQuotaUsed) { comp = -1;
/*     */       }
/* 364 */       return this.sortAscending ? comp : -comp;
/*     */     }
/*     */   }
/*     */   
/*     */   public void docRights(List<AdminRight> relatedRights, List<String> notes)
/*     */   {
/* 370 */     relatedRights.add(Rights.Admin.R_getDomainQuotaUsage);
/*     */     
/* 372 */     notes.add("If a domain is specified, need the the domain right " + Rights.Admin.R_getDomainQuotaUsage.getName() + ".  If domain is not specified, only system admins are allowed.");
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/admin/GetQuotaUsage.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */